package com.scaner.sam.ui;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.hardware.Camera;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
import android.os.Vibrator;
import android.support.annotation.Keep;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.scaner.sam.R;
import com.scaner.sam.camera.CameraManager;
import com.scaner.sam.decode.CaptureActivityHandler;
import com.scaner.sam.decode.InactivityTimer;
import com.scaner.sam.general.RecogResult;
import com.scaner.sam.utils.ScreenUtils;
import com.scaner.sam.utils.Tools;
import com.scaner.sam.view.ScannerFinderView;

import java.io.IOException;

import cn.bertsir.zbar.utils.QRUtils;


public abstract class ScanerActivity extends Activity implements Callback, SensorEventListener, Camera.ShutterCallback {

    protected CaptureActivityHandler mCaptureActivityHandler;
    protected boolean mHasSurface;
    protected InactivityTimer mInactivityTimer;
    @Keep
    protected ScannerFinderView mQrCodeFinderView;
    protected SurfaceView mSurfaceView;
    protected ViewStub mSurfaceViewStub;
    protected SensorManager sensorManager;
    protected Sensor accelerormeterSensor;
    private RelativeLayout mScanLayout;
    protected RelativeLayout mScanerRootLayout;
    protected LinearLayout mScanerBottomLayout;
    protected RelativeLayout mScanerHandleLayout;
    protected Vibrator vibrator;
    private PowerManager.WakeLock wakeLock;

    @Keep
    protected boolean bIsAvailable = true; //是否扫描开关
    @Keep
    protected boolean isQrCodeOne = true; // 首先扫描条形码

    @Override
    public void onCreate(Bundle savedInstanceState) {
        ScreenUtils.init(this);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scanner);
        getPermission();
        initView();
        initData();
    }

    private void getPermission() {
        ActivityCompat.requestPermissions(ScanerActivity.this, new String[]{Manifest.permission.CAMERA}, 1);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 1) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {}
        }
    }

    @Keep
    public void addView2Root(View topView) {
        mScanerRootLayout.addView(topView);
    }

    @Keep
    public void addView2ScanerHandle(View topView) {
        mScanerHandleLayout.addView(topView);
    }

    @Keep
    public void addView2BottomLayout(View view) {
        mScanerBottomLayout.addView(view);
    }

    @Keep
    public void addView2BottomLayout(View view, int index) {
        mScanerBottomLayout.addView(view, index);
    }

    @Keep
    public void openFlash(boolean isOpen) {
        CameraManager.get().setFlashLight(isOpen);
    }

    @Keep
    public void showTestView() {
    }

    private void initView() {
        mQrCodeFinderView = findViewById(R.id.qr_code_view_finder);
        mScanLayout = findViewById(R.id.rl_scaner_layout);
        mScanerRootLayout = findViewById(R.id.rl_root);
        mSurfaceViewStub = findViewById(R.id.qr_code_view_stub);
        mScanerBottomLayout = findViewById(R.id.ll_scaner_bottom);
        mScanerHandleLayout = findViewById(R.id.rl_handle_layout);
        mQrCodeFinderView.setIsTouch(false);
        mQrCodeFinderView.setIsDrawText(false);
        //dialog 高度
        mHasSurface = false;
    }

    @Keep
    public ScannerFinderView getQrCodeFinderView() {
        return mQrCodeFinderView;
    }

    @Keep
    public Rect getCropRect() {
        return mQrCodeFinderView.getRect();
    }

    @Keep
    public void showScanerHandleLayout(boolean isShow) {
        mScanLayout.setVisibility(isShow ? View.VISIBLE : View.GONE);
        mScanerBottomLayout.setVisibility(isShow ? View.VISIBLE : View.GONE);
        mScanerHandleLayout.setVisibility(!isShow ? View.VISIBLE : View.GONE);
    }

    @Keep
    public void setTopMargin(int topMargin) {
        RelativeLayout.LayoutParams scanLayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
        scanLayoutParams.topMargin = Tools.dip2px(getApplicationContext(), topMargin);
        mScanLayout.setLayoutParams(scanLayoutParams);
        mScanerHandleLayout.setLayoutParams(scanLayoutParams);
    }

    @Keep
    public void setTopMarginPx(int topMargin) {
        RelativeLayout.LayoutParams scanLayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
        scanLayoutParams.topMargin = topMargin;
        mScanLayout.setLayoutParams(scanLayoutParams);
        mScanerHandleLayout.setLayoutParams(scanLayoutParams);
    }

    @SuppressLint("InvalidWakeLockTag")
    private void initData() {
        vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
        wakeLock = ((PowerManager) getSystemService(POWER_SERVICE)).newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, "WakeLockActivity");
        sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        accelerormeterSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mInactivityTimer = new InactivityTimer(this);

    }

    @Override
    protected void onResume() {
        super.onResume();
        CameraManager.init();
        QRUtils.myEngine.initEngine();
        initCamera();
        if (accelerormeterSensor != null)
            sensorManager.registerListener(this, accelerormeterSensor, SensorManager.SENSOR_DELAY_GAME);

        if (wakeLock != null)
            wakeLock.acquire();
    }

    @Keep
    public void setStopPeriView() {
        mCaptureActivityHandler.onPause();
    }

    private void initCamera() {
        if (null == mSurfaceView) {
            mSurfaceViewStub.setLayoutResource(R.layout.layout_surface_view);
            mSurfaceView = (SurfaceView) mSurfaceViewStub.inflate();
        }
        SurfaceHolder surfaceHolder = mSurfaceView.getHolder();
        if (mHasSurface) {
            initCamera(surfaceHolder);
        } else {
            surfaceHolder.addCallback(this);
            surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        }
    }

    @Override
    protected void onDestroy() {
        if (null != mInactivityTimer) {
            mInactivityTimer.shutdown();
        }
        super.onDestroy();
    }

    @Override
    protected void onPause() {
        if (mCaptureActivityHandler != null) {
            try {
                mCaptureActivityHandler.quitSynchronously();
                mCaptureActivityHandler = null;
                if (null != mSurfaceView && !mHasSurface) {
                    mSurfaceView.getHolder().removeCallback(this);
                }
                CameraManager.get().closeDriver();
            } catch (Exception e) {
            }
        }
        super.onPause();
    }

    /**
     * Handler scan result
     *
     * @param result
     */
    public void handleDecode(RecogResult result) {
        mInactivityTimer.onActivity();
        handleResult(result);
    }

    private void initCamera(SurfaceHolder surfaceHolder) {
        try {
            if (!CameraManager.get().openDriver(surfaceHolder)) {
                return;
            }
        } catch (IOException e) {
            finish();
            return;
        } catch (RuntimeException re) {
            re.printStackTrace();
            return;
        }
        mQrCodeFinderView.setVisibility(View.VISIBLE);
        if (mCaptureActivityHandler == null) {
            mCaptureActivityHandler = new CaptureActivityHandler(this);
        }
    }

    @Keep
    public void restartPreview() {
        if (null != mCaptureActivityHandler) {
            try {
                mCaptureActivityHandler.restartPreviewAndDecode();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Keep
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    }

    @Keep
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        if (!mHasSurface) {
            mHasSurface = true;
            initCamera(holder);
        }
    }

    @Keep
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mHasSurface = false;
    }

    @Keep
    public Handler getCaptureActivityHandler() {
        return mCaptureActivityHandler;
    }
    @Keep
    long scanPhoneTime = 0;
    @Keep
    protected String lineNum = "";
    @Keep
    protected String phoneNum = "";

    @Keep
    protected void handleResult(RecogResult result) {
        if (!isAvailable()) return;
        if (isQrCodeOne) {
            if (result.m_lineNumber.length() < 8) return;
            lineNum = result.m_lineNumber;
            isQrCodeOne = false;
            scanPhoneTime = System.currentTimeMillis();
            restartPreview();

        } else {
            if (vibrator != null) vibrator.vibrate(200L);
            phoneNum = makePhoneNumberTypeString(result.m_szNumber);
            isQrCodeOne = true;
            bIsAvailable = false;
        }
    }

    @Keep
    public void initScan() {
        lineNum = "";
        phoneNum = "";
        bIsAvailable = true;
        isQrCodeOne = true;
        restartPreview();
    }

    @Keep
    public static String MakePhoneNumberTypeString(char[] szNumber) {
        String full = String.valueOf(szNumber);
        String typeStr = full.substring(0, 3) + "-" + full.substring(3, 7) + "-" + full.substring(7, 11);
        return typeStr;
    }

    @Keep
    public static String makePhoneNumberTypeString(char[] szNumber) {
        String full = String.valueOf(szNumber);
        String typeStr = full.substring(0, 11);
        return typeStr;
    }

    @Keep
    public void setIsAvailable(boolean isAvailable) {
        this.bIsAvailable = isAvailable;
    }

    @Keep
    public boolean isAvailable() {
        return bIsAvailable;
    }

    @Keep
    public boolean isQrCodeOne() {
        return isQrCodeOne;
    }

    @Keep
    public void setIsQrCodeOne(boolean isQrCodeOnes) {
        isQrCodeOne = isQrCodeOnes;
    }

    @Keep
    public void onShutter() {
    }

    private long lastTime;

    private float lastX;
    private float lastY;
    private float lastZ;

    @Keep
    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {

            long currentTime = System.currentTimeMillis();
            long gabOfTime = (currentTime - lastTime);
            if (gabOfTime > 1000 && bIsAvailable == true) {
                lastTime = currentTime;
                float x = event.values[0];
                float y = event.values[1];
                float z = event.values[2];

                lastX = x;
                lastY = y;
                lastZ = z;
                float deltaX = Math.abs(lastX - x);
                float deltaY = Math.abs(lastY - y);
                float deltaZ = Math.abs(lastZ - z);


                //通过计算重力感应来激活自动对焦
                if (deltaX > .2) {
                    restartPreview();
                }
                if (deltaY > .2) {
                    restartPreview();

                }
                if (deltaZ > 0.2) {
                    restartPreview();

                }

                lastX = x;
                lastY = y;
                lastZ = z;

            }
        }

    }

    @Keep
    @Override
    public void onAccuracyChanged(Sensor sensor, int i) {

    }
}